[Android][Framework]系统手势和状态栏


PhoneWindowManager.java

PhoneWindowManager在init的时候会监听系统手势:

/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
                 WindowManagerFuncs windowManagerFuncs) {
...
// monitor for system gestures
mSystemGestures = new SystemGesturesPointerEventListener(context,
new SystemGesturesPointerEventListener.Callbacks() {
    @Override
    public void onSwipeFromTop() {
        if (mStatusBar != null) {
            requestTransientBars(mStatusBar);
        }
    }
    @Override
    public void onSwipeFromBottom() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onSwipeFromRight() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onSwipeFromLeft() {
        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
            requestTransientBars(mNavigationBar);
        }
    }
    @Override
    public void onFling(int duration) {
        if (mPowerManagerInternal != null) {
            mPowerManagerInternal.powerHint(
                    PowerManagerInternal.POWER_HINT_INTERACTION, duration);
        }
    }
    @Override
    public void onDebug() {
        // no-op
    }
    @Override
    public void onDown() {
        mOrientationListener.onTouchStart();
    }
    @Override
    public void onUpOrCancel() {
        mOrientationListener.onTouchEnd();
    }
    @Override
    public void onMouseHoverAtTop() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
        mHandler.sendMessageDelayed(msg, 500);
    }
    @Override
    public void onMouseHoverAtBottom() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
        mHandler.sendMessageDelayed(msg, 500);
    }
    @Override
    public void onMouseLeaveFromEdge() {
        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
    }
});
    ...
}

监听使用的是SystemGesturesPointerEventListener

/*
 * Listens for system-wide input gestures, firing callbacks when detected.
 * @hide
 */
public class SystemGesturesPointerEventListener implements PointerEventListener {

由注释可见,这个Listener监听系统级别的输入手势,由回调触发处理。

这个Listener实现了一个接口:

public interface PointerEventListener {
    /**
     * 1. onPointerEvent will be called on the service.UiThread.
     * 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
     * copy() must be made and the copy must be recycled.
     **/
    public void onPointerEvent(MotionEvent motionEvent);
}

这个接口位于WindowManagerPolicy,是一个比较关键的接口。

回到Listener,看一下其对这个接口的具体实现:

@Override
public void onPointerEvent(MotionEvent event) {
    if (mGestureDetector != null && event.isTouchEvent()) {
        mGestureDetector.onTouchEvent(event);
    }
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            mSwipeFireable = true;
            mDebugFireable = true;
            mDownPointers = 0;
            captureDown(event, 0);
            if (mMouseHoveringAtEdge) {
                mMouseHoveringAtEdge = false;
                mCallbacks.onMouseLeaveFromEdge();
            }
            mCallbacks.onDown();
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            captureDown(event, event.getActionIndex());
            if (mDebugFireable) {
                mDebugFireable = event.getPointerCount() < 5;
                if (!mDebugFireable) {
                    if (DEBUG) Slog.d(TAG, "Firing debug");
                    mCallbacks.onDebug();
                }
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (mSwipeFireable) {
                final int swipe = detectSwipe(event);
                mSwipeFireable = swipe == SWIPE_NONE;
                if (swipe == SWIPE_FROM_TOP) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
                    mCallbacks.onSwipeFromTop();
                } else if (swipe == SWIPE_FROM_BOTTOM) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom");
                    mCallbacks.onSwipeFromBottom();
                } else if (swipe == SWIPE_FROM_RIGHT) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight");
                    mCallbacks.onSwipeFromRight();
                } else if (swipe == SWIPE_FROM_LEFT) {
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromLeft");
                    mCallbacks.onSwipeFromLeft();
                }
            }
            break;
        case MotionEvent.ACTION_HOVER_MOVE:
            if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
                if (!mMouseHoveringAtEdge && event.getY() == 0) {
                    mCallbacks.onMouseHoverAtTop();
                    mMouseHoveringAtEdge = true;
                } else if (!mMouseHoveringAtEdge && event.getY() >= screenHeight - 1) {
                    mCallbacks.onMouseHoverAtBottom();
                    mMouseHoveringAtEdge = true;
                } else if (mMouseHoveringAtEdge
                        && (event.getY() > 0 && event.getY() < screenHeight - 1)) {
                    mCallbacks.onMouseLeaveFromEdge();
                    mMouseHoveringAtEdge = false;
                }
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            mSwipeFireable = false;
            mDebugFireable = false;
            mCallbacks.onUpOrCancel();
            break;
        default:
            if (DEBUG) Slog.d(TAG, "Ignoring " + event);
    }
}

其中mCallbacks就是

    interface Callbacks {
        void onSwipeFromTop();
        void onSwipeFromBottom();
        void onSwipeFromRight();
        void onSwipeFromLeft();
        void onFling(int durationMs);
        void onDown();
        void onUpOrCancel();
        void onMouseHoverAtTop();
        void onMouseHoverAtBottom();
        void onMouseLeaveFromEdge();
        void onDebug();
    }

即定义好的10种手势。

里面switch语句处理的操作也是MotionEvent最基本的操作。这里主要看一下从上往下滑动的事件是怎么计算的:

case MotionEvent.ACTION_MOVE:
    if (mSwipeFireable) {
        final int swipe = detectSwipe(event);
        mSwipeFireable = swipe == SWIPE_NONE;
        if (swipe == SWIPE_FROM_TOP) {
            if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
            mCallbacks.onSwipeFromTop();
  1. 在MotionEvent.ACTION_DOWN的时候,将mSwipeFireable置为true
  2. 通过detectSwipe()方法计算滑动方向
  3. 确定SWIPE_FROM_TOP事件,调用对应回调

来看看detectSwipe方法,具体见注释。

private int detectSwipe(MotionEvent move) {
    // 返回此event中历史的点数
    final int historySize = move.getHistorySize();
    final int pointerCount = move.getPointerCount();
    for (int p = 0; p < pointerCount; p++) {
        final int pointerId = move.getPointerId(p);
        final int i = findIndex(pointerId);
        if (i != UNTRACKED_POINTER) {
            for (int h = 0; h < historySize; h++) {
                // 两次事件的间隔
                final long time = move.getHistoricalEventTime(h);
                final float x = move.getHistoricalX(p, h);
                final float y = move.getHistoricalY(p,  h);
                final int swipe = detectSwipe(i, time, x, y);
                if (swipe != SWIPE_NONE) {
                    return swipe;
                }
            }
            final int swipe = detectSwipe(i, move.getEventTime(), move.getX(p), move.getY(p));
            if (swipe != SWIPE_NONE) {
                return swipe;
            }
        }
    }
    return SWIPE_NONE;
}

private int detectSwipe(int i, long time, float x, float y) {
    final float fromX = mDownX[i];
    final float fromY = mDownY[i];
    final long elapsed = time - mDownTime[i];
    if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i]
            + " moved (" + fromX + "->" + x + "," + fromY + "->" + y + ") in " + elapsed);
    if (fromY <= mSwipeStartThreshold/*status_bar_height 意味着从status_bar范围内开始*/
            && y > fromY + mSwipeDistanceThreshold/*status_bar_height 划出status_bar范围*/
            && elapsed < SWIPE_TIMEOUT_MS/*500ms*/) {
        return SWIPE_FROM_TOP;
    }
    if (fromY >= screenHeight - mSwipeStartThreshold
            && y < fromY - mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_BOTTOM;
    }
    if (fromX >= screenWidth - mSwipeStartThreshold
            && x < fromX - mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_RIGHT;
    }
    if (fromX <= mSwipeStartThreshold
            && x > fromX + mSwipeDistanceThreshold
            && elapsed < SWIPE_TIMEOUT_MS) {
        return SWIPE_FROM_LEFT;
    }
    return SWIPE_NONE;
}

文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
  目录